package com.orange.notificationsummary.event.db;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;

import com.orange.common.utils.CharacterSets;
import com.orange.common.utils.EncodedStringValue;
import com.orange.notificationsummary.R;
import com.orange.notificationsummary.entry.DBConstants;
import com.orange.notificationsummary.event.MessageInfo;
import com.orange.notificationsummary.event.pil.defaultimpl.BaseEvent;
import com.orange.notificationsummary.event.pil.defaultimpl.MmsEvent;
import com.orange.notificationsummary.event.pil.defaultimpl.SmsEvent;
import com.orange.notificationsummary.utils.Constants;
import com.orange.notificationsummary.utils.Constants.EventType;
import com.orange.notificationsummary.utils.EventLSWidgetUtils;
import com.orange.notificationsummary.utils.LogHelper;
import com.orange.notificationsummary.utils.VipUtils;

public class MessagesDBHelper implements BaseColumns {
	private static final String		TAG							= "MessagesDBHelper";

	private static final String		ADDRESS						= "address";
	private static final String		AUDIO_MIME_TYPE_PREFIX		= "audio/";
	private static final String		IMAGE_MIME_TYPE_PREFIX		= "image/";
	private static final String		MSG_SELECTION				= "read=0";
	private static final String		MULTIPART_MIME_TYPE_PREFIX	= "multipart/";
	private static final String		TEXT_MIME_TYPE_PREFIX		= "text/";
	private static final String		VIDEO_MIME_TYPE_PREFIX		= "video/";

	private static final String[]	MMS_PART_PROJECTION			= new String[] {
			_ID, "mid", "seq", "ct", "cl", "_data", "text"		};
	private static final String[]	MMS_PDU_PROJECTION			= new String[] {
			"date", "ct_l"										};
	private static final String[]	MSG_PROJECTION				= { _ID,
			"date", "message_count", "recipient_ids", "snippet", "snippet_cs",
			"read", "error", "has_attachment"					};

	private static final Uri		MMS_PART_URI				= Uri.parse("content://mms/part");
	private static final Uri		MMS_SMS_ADDRESS_URI			= Uri.parse("content://mms-sms/canonical-addresses");
	private static final Uri		MMS_SMS_URI					= Uri.parse("content://mms-sms");
	private static final Uri		URI_MMS_INBOX				= Uri.parse("content://mms/inbox");
	private static final Uri		URI_SMS_INBOX				= Uri.parse("content://sms/inbox");
	private static final Uri		MSG_QUERY_URI				= Uri.withAppendedPath(
																		MMS_SMS_URI,
																		"conversations")
																		.buildUpon()
																		.appendQueryParameter(
																				"simple",
																				"true")
																		.build();

	private static final int		MESSAGE_SMS					= 0x1;
	private static final int		MESSAGE_MMS					= MESSAGE_SMS + 1;
	private static final int		STATUS_UNREAD				= 0x1;
	// private static final int STATUS_READ = STATUS_UNREAD + 1;
	// private static final int STATUS_ALL = STATUS_READ + 1;

	private Context					mContext;

	public MessagesDBHelper(Context context) {
		mContext = context;
	}

	private String extractEncodeString(String rawString, int charset) {
		if (TextUtils.isEmpty(rawString)) {
			return "";
		} else if (charset == CharacterSets.ANY_CHARSET) {
			return rawString;
		} else {
			return new EncodedStringValue(charset, getBytes(rawString))
					.getString();
		}
	}

	private String getThreadAddress(long threadId) {
		StringBuilder addressBuilder = new StringBuilder();
		Cursor recipients = null;
		try {
			recipients = mContext.getContentResolver().query(
					Uri.parse("content://mms-sms/conversations/" + threadId
							+ "/recipients"),
					new String[] { ThreadsColumns._ID,
							ThreadsColumns.RECIPIENT_IDS }, null, null, null);
		} catch (Exception e) {
			LogHelper.e(TAG, "getThreadAddress. ", e);
			if (recipients != null) {
				recipients.close();
				
				recipients = null;
			}
		}

		if (recipients != null) {
			try {
				if (recipients.moveToFirst()) {
					String RecipientIds = recipients.getString(recipients
							.getColumnIndex(ThreadsColumns.RECIPIENT_IDS));
					if (RecipientIds != null) {
						String[] recipientIdArray = RecipientIds.split(" ");
						boolean firstItem = true;

						for (String recipientId : recipientIdArray) {
							String singleAddress = null;
							Uri uri = null;
							if (recipientId != null) {
								uri = Uri
										.parse("content://mms-sms/canonical-address/"
												+ recipientId);
							}

							Cursor tempcur = null;
							try {
								tempcur = mContext.getContentResolver().query(
										uri, null, null, null, null);
							} catch (Exception e) {
								LogHelper.e(TAG, "getThreadAddress. ", e);
								tempcur = null;
							}

							if (tempcur != null) {
								try {
									if (tempcur.moveToFirst()) {
										int addressColumn = tempcur
												.getColumnIndex("address");
										singleAddress = tempcur
												.getString(addressColumn);
									}
								} finally {
									tempcur.close();
								}
							}

							if (singleAddress == null) {
								continue;
							}
							if (firstItem) {
								firstItem = false;
							} else {
								addressBuilder.append(",");
							}
							addressBuilder.append(singleAddress);
						}// End for

					}

				}
			} finally {
				recipients.close();
			}
		}

		return addressBuilder.toString();
	}

	private MessageInfo queryMessageInfo(Cursor c, int msgType) {

		int messageId;
		long threadId;
		int readStatus;
		String number;
		long messageDate;
		String smsContent = null;
		String mmsSubject = null;
		String mmsContent = null;

		if (msgType == MESSAGE_SMS) {
			messageId = c.getInt(c.getColumnIndex(SmsColumns._ID));
			threadId = c.getLong(c.getColumnIndex(SmsColumns.THREAD_ID));
			readStatus = c.getInt(c.getColumnIndex(SmsColumns.READ));
			number = c.getString(c.getColumnIndex(SmsColumns.ADDRESS));
			messageDate = c.getLong(c.getColumnIndex(SmsColumns.DATE));
			smsContent = c.getString(c.getColumnIndex(SmsColumns.BODY));
		} else {
			messageId = c.getInt(c.getColumnIndex(MmsColumns._ID));
			threadId = c.getLong(c.getColumnIndex(MmsColumns.THREAD_ID));
			readStatus = c.getInt(c.getColumnIndex(MmsColumns.READ));
			number = getThreadAddress(threadId);
			messageDate = c.getLong(c.getColumnIndex(MmsColumns.DATE)) * 1000;
			String rawSubject = c.getString(c
					.getColumnIndex(MmsColumns.SUBJECT));
			int charset = c
					.getInt(c.getColumnIndex(MmsColumns.SUBJECT_CHARSET));

			mmsSubject = extractEncodeString(rawSubject, charset);
			mmsContent = getMmsTextContent(mContext, String.valueOf(messageId));
		}

		LogHelper.i(TAG, "queryMessageInfo. smsContent: " + smsContent
				+ " , mmsSubject: " + mmsSubject + " , mmsContent: "
				+ mmsContent);

		MessageInfo info = new MessageInfo(messageId, msgType, threadId,
				readStatus, number, messageDate, smsContent, mmsSubject,
				mmsContent);

		return info;
	}

	public synchronized List<MessageInfo> queryMessages(int msgType, int msgFlag) {
		ArrayList<MessageInfo> msgList = new ArrayList<MessageInfo>();
		if (EventLSWidgetUtils.isPackageExist(mContext,
				Constants.PKG_NOTIFICATION_SUMMARY)
				&& EventLSWidgetUtils.getNotifictionTypesIsChecked(mContext,
						Constants.KEY_WIDGET_EVENT_DETAIL_MESSAGE)) {
			Uri uri = null;
			String selection = null;

			if (msgFlag == STATUS_UNREAD) {
				// selection = "read = 0";
				selection = DBConstants.UNREAD;
			}

			if (msgType == MESSAGE_SMS) {
				uri = URI_SMS_INBOX;
			} else {
				uri = URI_MMS_INBOX;
			}

			Cursor c = null;
			try {
				// TODO:order need custom
				c = mContext.getContentResolver().query(uri, null, selection,
						null, DBConstants.SORT_DATE);
			} catch (Exception e) {
				LogHelper.e(TAG, "queryMessages. ", e);
				c = null;
			}

			if (c != null) {
				if (c.moveToFirst()) {
					do {
						MessageInfo info = queryMessageInfo(c, msgType);
						msgList.add(info);
					} while (c.moveToNext());
				}
				c.close();
			}
		}
		return msgList;
	}

	public void setContext(Context context) {
		mContext = context;
	}

	public interface MmsColumns extends BaseColumns {
		/* The date the message was sent.: INTEGER (long) */
		public static final String	DATE			= "date";

		/* The Message-ID of the message.: TEXT */
		public static final String	MESSAGE_ID		= "m_id";

		/* Has the message been read.: INTEGER (boolean) */
		public static final String	READ			= "read";

		/* The subject of the message, if present.: TEXT */
		public static final String	SUBJECT			= "sub";

		/* The character set of the subject, if present.: INTEGER */
		public static final String	SUBJECT_CHARSET	= "sub_cs";

		public static final String	TEXT			= "text";

		/* The thread ID of the message: INTEGER */
		public static final String	THREAD_ID		= "thread_id";

	}

	public interface SmsColumns extends BaseColumns {
		/* The address of the other party: TEXT */
		public static final String	ADDRESS		= "address";

		/* The body of the message : TEXT */
		public static final String	BODY		= "body";

		/* The date the message was sent : INTEGER (long) */
		public static final String	DATE		= "date";

		/* Has the message been read: INTEGER (boolean) */
		public static final String	READ		= "read";

		/* The thread ID of the message: INTEGER */
		public static final String	THREAD_ID	= "thread_id";
	}

	public interface ThreadsColumns extends BaseColumns {
		/*
		 * A string encoding of the recipient IDs of the recipients of the
		 * message, in numerical order and separated by spaces.: TEXT
		 */
		public static final String	RECIPIENT_IDS	= "recipient_ids";
	}

	/**
	 * get unread message info list
	 * 
	 * @return
	 */
	public static List<BaseEvent> getAllUnreadMessageEvent(Context context) {
		List<BaseEvent> messageEvents = null;
		List<MessageInfo> mUnreadMsgs = null;

		Map<String, String> numberContactMap = new HashMap<String, String>();
		Map<String, Bitmap> contactPhotoMap = new HashMap<String, Bitmap>();
		Map<String, Bitmap> mmsPhotoMap = new HashMap<String, Bitmap>();
		Map<String, String> contactDisplayNameMap = new HashMap<String, String>();
		Map<String, String> numberTypeMap = new HashMap<String, String>();
		Map<String, Integer> numberCountMap = new HashMap<String, Integer>();

		Cursor phoneNumberCursor = null;
		try {
			phoneNumberCursor = NotificationDBHelper
					.getAllPhoneNumberCursor(context);
		} catch (Exception ex) {
			LogHelper.e(TAG, "getAllUnreadMessageEvent. Query contact error",
					ex);
		}

		mUnreadMsgs = getUnreadMmsSmsInfo(context);

		if (mUnreadMsgs != null) {
			LogHelper.d(TAG, "getAllUnreadMessageEvent. mUnreadMsgs.size:"
					+ mUnreadMsgs.size());
			messageEvents = new ArrayList<BaseEvent>();
			for (MessageInfo ms : mUnreadMsgs) {
				BaseEvent event = null;

				if (ms.getMsgType() == MessagesDBHelper.MESSAGE_SMS) {
					event = new SmsEvent(context);
				} else if (ms.getMsgType() == MessagesDBHelper.MESSAGE_MMS) {
					event = new MmsEvent(context);
				}

				event.id = ms.getMsgId();
				event.threadId = ms.getThreadId();
				event.evnet_number = ms.getAddress();
				event.event_date = ms.getDate();
				event.event_type_name = context.getResources().getString(
						R.string.unread_msg_event_name);
				event.event_type = EventType.UNMSG_UPDATE;
				event.event_type_image = context.getResources().getDrawable(
						R.drawable.icon_message_24);
				event.contacts_id = NotificationDBHelper
						.getContactIdByPhoneNumber(context, event.evnet_number,
								phoneNumberCursor, numberContactMap);// getContactId(event.evnet_number);
				if (ms.getMsgType() == MessagesDBHelper.MESSAGE_MMS) {
					event.isAttVisible = isAttchmentIconVisible(context,
							event.id);
				}
				if (event.contacts_id != null) {
					if (ms.getMsgType() == MessagesDBHelper.MESSAGE_SMS) { // sms
						event.contacts_image = NotificationDBHelper
								.getContactPhotoByContactId(context,
										event.contacts_id, contactPhotoMap);
						event.isVip = VipUtils
								.isVip(context, event.contacts_id);
						event.isInContacts = true;
					} else { // mms
						setContactMmsImageVip(context, event, mmsPhotoMap,
								contactPhotoMap);
					}

					event.evnet_name = NotificationDBHelper
							.getDisplayNameByMap(context, event.contacts_id,
									contactDisplayNameMap);// getDisplayName(event.contacts_id);
					event.phoneNumberCount = NotificationDBHelper
							.getContactNumberCountByMap(context,
									event.contacts_id, numberCountMap);
				} else {
					event.isVip = false;

					if (ms.getMsgType() == MessagesDBHelper.MESSAGE_SMS) {
						event.mms_one_image = null;
						event.contacts_image = null;
					} else if (ms.getMsgType() == MessagesDBHelper.MESSAGE_MMS) {
						setNoContactMmsImageVip(context, event, contactPhotoMap);
					}
				}

				event.evnet_number_type = NotificationDBHelper
						.getNumberTypeByMap(context, event.evnet_number,
								numberTypeMap);

				event.event_mms_subject = ms.getMmsSubject();
				event.event_mms_content = ms.getMmsContent();
				event.event_sms_content = ms.getSmsContent();

				MessageInfo info = getEventSinppetInThreads(context, _ID
						+ " = " + event.threadId);

				if (info != null) {
					event.event_mmssubject_smscontent = info.getSnippet();
					event.threads_recipient = info.getRecipientId();
					LogHelper.v(TAG, "getAllUnreadMessageEvent. snippet: "
							+ event.event_mmssubject_smscontent
							+ " , recipient: " + event.threads_recipient);

				}
				messageEvents.add(event);
			}
		}
		
		// 20120214 added for closing the Cursor.
		// TODO: Fix the cursor init position.
		if (phoneNumberCursor != null) {
			phoneNumberCursor.close();
		}
		return messageEvents;
	}

	public static Map<String, Integer> getAttachementCount(Context context,
			String mId) {
		Map<String, Integer> attMap = new HashMap<String, Integer>();

		int attImageCount = 0;
		int attTextPlainCount = 0;
		int attGenericCount = 0;

		if (mId != null) {
			Cursor cursor = null;
			try {
				cursor = context.getContentResolver().query(MMS_PART_URI,
						MMS_PART_PROJECTION, "mid=?", new String[] { mId },
						"seq ASC");

				if (cursor != null) {
					// int idIndex = cursor.getColumnIndex("_id");
					// int dataIndex = cursor.getColumnIndex("_data");
					int ctIndex = cursor.getColumnIndex("ct");

					while (cursor.moveToNext()) {
						String ct = cursor.getString(ctIndex);
						if (ct != null) {
							if (ct.startsWith(TEXT_MIME_TYPE_PREFIX)) {
								if (ct.contains("text/plain")) {
									attTextPlainCount++;
								} else {
									attGenericCount++;
								}
							} else if (ct.startsWith(IMAGE_MIME_TYPE_PREFIX)) {
								attImageCount++;
							} else if (ct.startsWith(AUDIO_MIME_TYPE_PREFIX)
									|| ct.startsWith(VIDEO_MIME_TYPE_PREFIX)
									|| ct.startsWith(MULTIPART_MIME_TYPE_PREFIX)
							// ct .startsWith(APPLICATION_MIME_TYPE_PREFIX)
							) {
								attGenericCount++;
							}
						}
					}

					attMap.put(Constants.KEY_MMS_ATTACHMENT_IMAGE,
							attImageCount);
					if (attTextPlainCount != 0) {
						attTextPlainCount = 1;
					}
					attMap.put(Constants.KEY_MMS_ATTACHMENT_TEXTPLAIN,
							attTextPlainCount);
					attMap.put(Constants.KEY_MMS_ATTACHMENT_GENERIC,
							attGenericCount);

					LogHelper.v(TAG, "getAttachementCount. attImageCount: "
							+ attImageCount + " , attTextPlainCount: "
							+ attTextPlainCount + " , attGenericCount: "
							+ attGenericCount);

				}
			} catch (Exception e) {
				LogHelper.e(TAG, "getAttachementCount. ", e);
			} finally {
				if (cursor != null)
					cursor.close();
			}
		}

		return attMap;
	}

	/**
	 * Unpack a given String into a byte[].
	 */
	public static byte[] getBytes(String data) {
		try {
			return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
		} catch (UnsupportedEncodingException e) {
			return new byte[0];
		}
	}

	public static MessageInfo getEventSinppetInThreads(Context context,
			String selection) {
		String snippet = null;
		String recipient_ids = null;
		MessageInfo info = null;

		Cursor cursor = null;
		try {
			cursor = context.getContentResolver().query(MSG_QUERY_URI,
					MSG_PROJECTION, selection, null, DBConstants.SORT_DATE);
			if (cursor != null && cursor.moveToFirst()) {
				int snippetIndex = cursor.getColumnIndex("snippet");
				int recipientIndex = cursor.getColumnIndex("recipient_ids");
				snippet = cursor.getString(snippetIndex);
				recipient_ids = cursor.getString(recipientIndex);
			}

			if (!TextUtils.isEmpty(snippet)
					&& !TextUtils.isEmpty(recipient_ids)) {
				info = new MessageInfo(recipient_ids, snippet);
			}
		} catch (Exception e) {
		} finally {
			if (cursor != null) {
				cursor.close();
			}
		}

		return info;
	}

	private static Bitmap getMmsBitmap(byte[] arrayByte) {
		try {
			if (arrayByte != null) {
				Options opts = new Options();
				int originalW = opts.outWidth;
				int originalH = opts.outHeight;
				int outW = 124;
				int outH = 124;

				opts.inJustDecodeBounds = false;
				opts.inPreferredConfig = Config.RGB_565;
				opts.inSampleSize = Math
						.min(originalW / outW, originalH / outH);

				Bitmap bm = BitmapFactory.decodeByteArray(arrayByte, 0,
						arrayByte.length, opts);
				return bm;
			} else {
				return null;
			}
		} catch (OutOfMemoryError e) {
			LogHelper.e(TAG, "getMmsBitmap. ", e);
			System.gc();
			return null;
		}
	}

	public static String getMMSContentLocationUrl(Context context, String id) {
		String ctlUrl = null;
		if (id != null) {
			Cursor cursor = null;
			try {
				cursor = context.getContentResolver().query(URI_MMS_INBOX,
						MMS_PDU_PROJECTION, "_id=?", new String[] { id },
						DBConstants.SORT_DATE);

				if (cursor != null) {
					int ctlIndex = cursor.getColumnIndex("ct_l");
					if (cursor.moveToFirst()) {
						ctlUrl = cursor.getString(ctlIndex);
					}
				}
			} catch (Exception e) {
				LogHelper.e(TAG, "getMMSContentLocationUrl. ", e);
			} finally {
				if (cursor != null)
					cursor.close();
			}
		}
		return ctlUrl;
	}

	private static Cursor getMmsInfoCursor(Context context, String mId) {
		Cursor cursor = null;
		if (mId != null) {
			try {
				cursor = context.getContentResolver().query(MMS_PART_URI,
						MMS_PART_PROJECTION, "mid=?", new String[] { mId },
						"seq ASC");
			} catch (Exception e) {
			}
		}
		return cursor;
	}

	/**
	 * the same to getUnreadMMSInfo()
	 * 
	 * @param context
	 * @param id
	 * @return
	 */
	public static Bitmap getMmsPhotobyMmsId(Context context, String id) {
		int _id = -1;
		Cursor cursor = null;

		try {
			cursor = getMmsInfoCursor(context, id);
			if (cursor != null && cursor.moveToFirst()) {
				int ctIndex = cursor.getColumnIndex("ct");
				int idIndex = cursor.getColumnIndex(_ID);

				do {
					String ct = cursor.getString(ctIndex);
					if (ct != null && ct.startsWith(IMAGE_MIME_TYPE_PREFIX)) {
						_id = cursor.getInt(idIndex);
						break;
					}
				} while (cursor.moveToNext());

			}
		} catch (Exception e) {
			LogHelper.e(TAG, "getMmsPhotobyMmsId. cursor error" + e);
		} finally {
			if (cursor != null) {
				cursor.close();
			}
		}

		// return _id;
		if (_id != -1) {
			return getMmsBitmap(getMmsPhotoContentByMmsPartId(context, _id));
		}
		return null;
	}

	private static Bitmap getMmsPhotoByMmsId(Context context, String mmsId,
			Map<String, Bitmap> map) {
		if (TextUtils.isEmpty(mmsId)) {
			return null;
		}
		if (map != null && map.containsKey(mmsId)) {
			return map.get(mmsId);
		} else {
			Bitmap bitmap = getMmsPhotobyMmsId(context, mmsId);
			if (map != null) {
				map.put(mmsId, bitmap);
				return bitmap;
			}
		}
		return null;
	}

	private static byte[] getMmsPhotoContentByMmsPartId(Context context,
			int partId) {
		Uri partUri = ContentUris.withAppendedId(MMS_PART_URI, partId);

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		InputStream is = null;
		try {
			is = context.getContentResolver().openInputStream(partUri);
			byte[] buffer = new byte[256];
			int len = is.read(buffer);
			while (len >= 0) {
				baos.write(buffer, 0, len);
				len = is.read(buffer);
			}
			if (baos != null) {
				return baos.toByteArray();
			}
		} catch (IOException e) {
			LogHelper.e(TAG, "getMmsPhotoContentByMmsPartId. ", e);
		}
		// return null;
		return new byte[0];
	}

	public static String getMmsTextContent(Context context, String mId) {
		Cursor cursor = null;
		String text = null;

		try {
			cursor = getMmsInfoCursor(context, mId);
			if (cursor != null && cursor.moveToFirst()) {
				int ctIndex = cursor.getColumnIndex("ct");
				int textIndex = cursor.getColumnIndex("text");

				do {
					String ct = cursor.getString(ctIndex);
					if (ct != null && ct.startsWith(TEXT_MIME_TYPE_PREFIX)) {
						text = cursor.getString(textIndex);
						break;
					}
				} while (cursor.moveToNext());
			}
		} catch (Exception e) {
		} finally {
			if (cursor != null) {
				cursor.close();
			}
		}

		return text;
	}

	/**
	 * @param id
	 * @return
	 */
	public static String getSmsNumber(Context context, String id) {
		String smsNumber = "";
		if (!TextUtils.isEmpty(id)) {
			Cursor cursor = null;
			try {
				cursor = context.getContentResolver().query(
						MMS_SMS_ADDRESS_URI, new String[] { ADDRESS },
						_ID + " = ?", new String[] { id }, null);

				while (cursor.moveToNext()) {
					for (int i = 0; i < cursor.getColumnCount(); i++) {
						smsNumber = cursor.getString(cursor
								.getColumnIndex(ADDRESS));
					}
				}
			} catch (Exception e) {
				LogHelper.e(TAG, "getSmsNumber. ", e);
			} finally {
				if (cursor != null)
					cursor.close();
			}
		}
		return smsNumber;
	}

	public static Cursor getThreadsInfoCursor(Context context) {
		Cursor cursor = null;
		try {
			cursor = context.getContentResolver().query(MSG_QUERY_URI,
					MSG_PROJECTION, MSG_SELECTION, null, DBConstants.SORT_DATE);
		} catch (Exception e) {
			LogHelper.e(TAG, "getThreadsInfoCursor. ", e);
		}
		return cursor;
	}

	public static List<MessageInfo> getUnreadMmsInfo(Context context) {
		MessagesDBHelper mdb = new MessagesDBHelper(context);
		List<MessageInfo> mUnreadMmss = null;
		if (mdb != null) {
			try {
				mUnreadMmss = mdb.queryMessages(MessagesDBHelper.MESSAGE_MMS,
						MessagesDBHelper.STATUS_UNREAD);
			} catch (Exception e) {
				LogHelper.e(TAG, "getUnreadMmsInfo. Query unread mms error", e);
			}
		}

		return mUnreadMmss;
	}

	/**
	 * Currently, Lockscreen only support "image/*" or "text/*" about MMS
	 * 
	 * @param context
	 * @param mId
	 * @return
	 */
	public static Map<String, String> getUnreadMMSInfo(Context context,
			String mId) {
		Map<String, String> MMSInfoMap = new HashMap<String, String>();
		String _id = null;
		String text = null;
		if (mId != null) {
			Cursor cursor = null;
			try {
				cursor = context.getContentResolver().query(MMS_PART_URI,
						MMS_PART_PROJECTION, "mid=?", new String[] { mId },
						"seq ASC");

				if (cursor != null) {
					int ctIndex = cursor.getColumnIndex("ct");
					int idIndex = cursor.getColumnIndex(_ID);
					int textIndex = cursor.getColumnIndex("text");

					while (cursor.moveToNext()) {
						String ct = cursor.getString(ctIndex);
						if (ct != null && ct.startsWith(IMAGE_MIME_TYPE_PREFIX)) {
							_id = cursor.getString(idIndex);
						}
						if (ct != null && ct.startsWith(TEXT_MIME_TYPE_PREFIX)) {
							text = cursor.getString(textIndex);
						}
					}
				}

			} catch (Exception e) {
				LogHelper.e(TAG, "getUnreadMMSInfo. ", e);
			} finally {
				if (cursor != null)
					cursor.close();
			}
		}
		MMSInfoMap.put(_ID, _id);
		MMSInfoMap.put("text", text);
		return MMSInfoMap;
	}

	public static List<MessageInfo> getUnreadMmsSmsInfo(Context context) {
		List<MessageInfo> mUnreadMsgs = null;
		List<MessageInfo> mUnreadMmss = null;
		// query unread sms
		mUnreadMsgs = getUnreadSmsInfo(context);

		// query unread mms
		mUnreadMmss = getUnreadMmsInfo(context);
		if (mUnreadMsgs != null && mUnreadMmss != null) {
			mUnreadMsgs.addAll(mUnreadMmss);
		} else if (mUnreadMmss != null && mUnreadMsgs == null) {
			mUnreadMsgs = mUnreadMmss;
		}

		return mUnreadMsgs;
	}

	public static List<MessageInfo> getUnreadSmsInfo(Context context) {
		MessagesDBHelper mdb = new MessagesDBHelper(context);
		List<MessageInfo> mUnreadMsgs = null;
		if (mdb != null) {
			try {
				mUnreadMsgs = mdb.queryMessages(MessagesDBHelper.MESSAGE_SMS,
						MessagesDBHelper.STATUS_UNREAD);
				LogHelper.d(TAG,
						"getUnreadSmsInfo. size: " + mUnreadMsgs.size());
			} catch (Exception e) {
				LogHelper.e(TAG, "getUnreadSmsInfo. Query unread sms error", e);
			}
		}

		return mUnreadMsgs;
	}

	/**
	 * return whether the mms attachment is download already
	 * @param context
	 * @param msgId
	 * @return
	 */
	private static boolean isMmsDownloadOver(Context context,int msgId){
		LogHelper.d("mms", "########### isMmsDownloadOver,msgId: " + msgId);
		boolean isDownloadOver = false;
		String mId = String.valueOf(msgId);
		if(null != mId){
			Cursor cursor = null;
			try {
				cursor = context.getContentResolver().query(Uri.parse("content://mms"),
						new String[]{"st"}, "_id=?", new String[] { mId },null);
				
				if(null != cursor) {
					cursor.moveToFirst();
					int stIndex = cursor.getColumnIndex("st");
					String st = cursor.getString(stIndex);
					/**
					 * st value 135: not downloadOver;null:downloadOver
					 */
					if(null == st){
						isDownloadOver = true;
					}else if(st.equals("135")){
						isDownloadOver = false;
					}
					Log.d("mms", "########### msgId : " + msgId+ ",isMmsDownloadOver ? " + isDownloadOver);
				}
			}catch(Exception e){
				e.printStackTrace();
			} finally {
				if (cursor != null) {
					cursor.close();
				}
			}
		}
		return isDownloadOver;
		
	}
	/**
	 * 
	 * @param context
	 * @param msgId
	 * @return
	 */
	private static boolean isAttchmentIconVisible(Context context, int msgId) {
		String mId = String.valueOf(msgId);
		LogHelper.i("download", "isAttchmentIconVisible. mId: " + mId);
		Map<String, Integer> attMap = MessagesDBHelper.getAttachementCount(
				context, mId);

		boolean isMmsDownloadOver = isMmsDownloadOver( context, msgId);
		int attImageCount = 0;
		int attGenericCount = 0;

		/**
		 * modify by gaoge 2011-12-08 for fix bug 0013710
		 */
		int attTextPlainCount = 0;
		
		if (attMap != null && !attMap.isEmpty()) {
			attImageCount = attMap.get(Constants.KEY_MMS_ATTACHMENT_IMAGE);
			attGenericCount = attMap.get(Constants.KEY_MMS_ATTACHMENT_GENERIC);
			attTextPlainCount = attMap.get(Constants.KEY_MMS_ATTACHMENT_TEXTPLAIN);
		}

		LogHelper.v(TAG, "isAttchmentIconVisible. attImageCount: "
				+ attImageCount + " , attGenericCount: " + attGenericCount);

		int attCount = attImageCount + attGenericCount;

		// if ((attCount > 1) || (attCount == 1 && attGenericCount == 1)) {
		// return true;
		// } else {
		// return false;
		// }
		// return attCount > 1 || (attCount == 1 && attGenericCount == 1);
		/**
		 * add by gaoge 2011-09-02,for fix bug 0013226,because when mms hasn't
		 * download already, the attCount is 0,in this case,we should also show
		 * the att Icon
		 */
//		return attCount > 1 || (attCount == 1 && attGenericCount == 1)
//				|| (0 == attCount);
		/**
		 * modify by gaoge 2011-12-08 for fix bug 0013710
		 */
//		return attCount > 1 || (attCount == 1 && attGenericCount == 1)
//		|| (0 == attCount && 0 == attTextPlainCount);
		
		/**
		 * modify by gaoge 2011-12-29,to make code more logical,but still have some little problem,
		 * when a mms with attachment received,the isMmsDownloadOver change seria is "true->false->true"
		 * so the attchment icon status is "not show->show->show",which more advanced than before
		 * "not show->not show->show"
		 */
		LogHelper.d("mms", "@@@@@@@@@@@@@@@@@ attCount: " + attCount + ",attGenericCount: " + attGenericCount
				+ ",isMmsDownloadOver: " + isMmsDownloadOver);
		return attCount > 1 || (attCount == 1 && attGenericCount == 1)
		|| (0 == attCount && !isMmsDownloadOver);
		
		
	}

	public static boolean isNotShowMMS(Context context, int mid) {
		boolean isShow = false;
		String selection = new String("mid='" + mid + "'");
		Cursor cursor = context.getContentResolver().query(MMS_PART_URI, null,
				selection, null, null);

		if (cursor != null && cursor.moveToFirst()) {
			isShow = true;
		}

		if (cursor != null) {
			cursor.close();
		}

		return isShow;
	}

	private static void setContactMmsImageVip(Context context, BaseEvent event,
			Map<String, Bitmap> mmsPhotoMap, Map<String, Bitmap> contactPhotoMap) {
		Map<String, Integer> attMap = getAttachementCount(context,
				String.valueOf(event.id));
		if (attMap != null
				&& attMap.containsKey(Constants.KEY_MMS_ATTACHMENT_IMAGE)
				&& attMap.containsKey(Constants.KEY_MMS_ATTACHMENT_GENERIC)) {
			int attImageCount = attMap.get(Constants.KEY_MMS_ATTACHMENT_IMAGE);
			int attGenericCount = attMap
					.get(Constants.KEY_MMS_ATTACHMENT_GENERIC);

			LogHelper.v(TAG, "setContactMmsImageVip. attImageCount: "
					+ attImageCount + " , attGenericCount: " + attGenericCount);

			Bitmap contactBitmap = null;
			// if (attImageCount == 1 && attGenericCount == 0) {
			// modify by gaoeg 2011-08-22 ,for fix bug 0013226
			if (attImageCount >= 1) {
				contactBitmap = getMmsPhotoByMmsId(context,
						Integer.toString(event.id), mmsPhotoMap);
				LogHelper.v(TAG, "setContactMmsImageVip. contactBitmap: "
						+ contactBitmap);
				event.mms_one_image = contactBitmap;
				event.isInMMSImage = true;
			} else {
				contactBitmap = NotificationDBHelper
						.getContactPhotoByContactId(context, event.contacts_id,
								contactPhotoMap);
				event.isVip = VipUtils.isVip(context, event.contacts_id);

				event.contacts_image = contactBitmap;
				event.isInContacts = true;
			}
		}
	}

	private static void setNoContactMmsImageVip(Context context,
			BaseEvent event, Map<String, Bitmap> mmsPhotoMap) {
		Map<String, Integer> attMap = getAttachementCount(context,
				String.valueOf(event.id));
		if (attMap != null
				&& attMap.containsKey(Constants.KEY_MMS_ATTACHMENT_IMAGE)
				&& attMap.containsKey(Constants.KEY_MMS_ATTACHMENT_GENERIC)) {
			int attImageCount = attMap.get(Constants.KEY_MMS_ATTACHMENT_IMAGE);
			int attGenericCount = attMap
					.get(Constants.KEY_MMS_ATTACHMENT_GENERIC);

			LogHelper.v(TAG, "setNoContactMmsImageVip. attImageCount: "
					+ attImageCount + " , attGenericCount: " + attGenericCount);

			Bitmap contactBitmap = null;
			// if (attImageCount == 1 && attGenericCount == 0) {
			// modify by gaoge 2011-08-29
			if (attImageCount >= 1) {
				contactBitmap = getMmsPhotoByMmsId(context,
						Integer.toString(event.id), mmsPhotoMap);

				event.mms_one_image = contactBitmap;

				if (contactBitmap != null) {
					event.isInMMSImage = true;
				}
			} else {
				event.contacts_image = null;
			}
		}
	}

	/**
	 * update SMS read status
	 * 
	 * @param context
	 * @param id
	 * @return
	 */
	public static boolean updateSMSStatusById(Context context, String id) {
		ContentValues values = new ContentValues();
		values.put("read", 1);
		try {
			Uri uri = Uri.withAppendedPath(URI_SMS_INBOX, id);
			context.getContentResolver().update(uri, values, null, null);
		} catch (Exception e) {
			LogHelper.e(TAG, "updateSMSStatusById. ", e);
			return false;
		}
		return true;
	}

}
